package ltd.jdsoft.cute.spring.web.logger;

import java.util.HashMap;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import com.alibaba.fastjson.JSONObject;

import ltd.jdsoft.cute.api.http.RestResponse;
import ltd.jdsoft.cute.spring.base.util.StopWatch;

/**
 * http请求/响应的日志，记录到数据库方便后续排查问题
 * 
 * @author zhengzhq
 *
 */
@Component
@Aspect
public class HttpRequestResponseLogger {

  private static Logger logger = LoggerFactory.getLogger(HttpRequestResponseLogger.class);

  @Around("@annotation(requestMapping)")
  public Object process(ProceedingJoinPoint joinPoint, RequestMapping requestMapping)
      throws Throwable {
    // 获取请求的url，如果没有配置@RequestMapping
    String[] urls = requestMapping.value();
    if (urls == null || urls.length == 0) {
      return joinPoint.proceed();
    }

    StopWatch watch = new StopWatch();
    watch.start();
    Object result = joinPoint.proceed();

    // 所有api的response都是RestResponse
    if (!(result instanceof RestResponse)) {
      return result;
    }

    try {
      // 获取请求数据
      HttpServletRequest request =
          ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
      Map<String, String[]> paramMap = new HashMap<>(request.getParameterMap());
      // 去掉签名sign、cooperator、reqMsgId字段
      paramMap.remove("sign");
      paramMap.remove("reqMsgId");
      paramMap.remove("cooperator");
      paramMap.remove("algorithm");

      watch.stop();
      logger.info("request url:{},request param: {}, response: {}, cost time: {}ms",
          new Object[] {urls[0], JSONObject.toJSONString(paramMap), JSONObject.toJSONString(result),
              watch.getDuration()});
    } catch (Exception e) {
      logger.error("log http request reponse info error", e);
    }

    return result;
  }
}
